package com.yuke.cloud.service.omc.controller.frontend;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.domain.AlipayTradeAppPayModel;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradeAppPayRequest;
import com.alipay.api.request.AlipayTradeRefundRequest;
import com.alipay.api.response.AlipayTradeAppPayResponse;
import com.alipay.api.response.AlipayTradeRefundResponse;
import com.yuke.cloud.common.base.dto.MsgNotificationBody;
import com.yuke.cloud.common.core.mq.RabbitSender;
import com.yuke.cloud.common.core.support.BaseController;
import com.yuke.cloud.common.util.BigDecimalUtil;
import com.yuke.cloud.common.util.HttpAesUtil;
import com.yuke.cloud.common.util.wrapper.WrapMapper;
import com.yuke.cloud.common.util.wrapper.Wrapper;
import com.yuke.cloud.service.api.cmc.service.CmcFeignApi;
import com.yuke.cloud.service.api.opc.service.OpcSendNotifyFeignApi;
import com.yuke.cloud.service.api.uac.dto.UserInfoDto;
import com.yuke.cloud.service.api.uac.service.UacUserFeignApi;
import com.yuke.cloud.service.omc.config.Iputil;
import com.yuke.cloud.service.omc.config.Unifiedorder;
import com.yuke.cloud.service.omc.config.wxconfig;
import com.yuke.cloud.service.omc.dto.OdsPointsDto;
import com.yuke.cloud.service.omc.entity.*;
import com.yuke.cloud.service.omc.payUtil.Alipayutil;
import com.yuke.cloud.service.omc.payUtil.payutil;
import com.yuke.cloud.service.omc.service.OdsBillService;
import com.yuke.cloud.service.omc.service.OdsOrderService;
import com.yuke.cloud.service.omc.service.OdsPayOrderService;
import com.yuke.cloud.service.omc.service.OdsTeamIntentService;
import io.swagger.annotations.ApiOperation;
import lombok.Synchronized;
import lombok.extern.slf4j.Slf4j;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Import;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.util.*;

import static com.yuke.cloud.service.omc.controller.frontend.WxPayController.isTenpaySign;
import static com.yuke.cloud.service.omc.controller.frontend.WxPayController.maptojson;

/*
 * <p>Company: Copyright (c) 2018. yuke All Rights Reserved. </br> </p>
 * <p>Title：yuke-mall </br> </p>
 * <p>com.yuke.cloud.service.omc.controller.frontend Description TODO </br> </p>
 * @Author wg
 * @Date   2019/10/16 15:49
 */
@RestController
@RequestMapping("/bill")
@Import(RabbitSender.class)
@Slf4j
public class OdsBillPayController extends BaseController {

    @Resource
    private OdsBillService odsBillService;
    @Resource
    private OdsOrderService odsOrderService;
    @Resource
    private OdsTeamIntentService odsTeamIntentService;
    @Resource
    private OpcSendNotifyFeignApi opcSendNotifyFeignApi;
    @Resource
    private OdsPayOrderService odsPayOrderService;
    @Resource
    private UacUserFeignApi uacUserFeignApi;
    @Resource
    private CmcFeignApi cmcFeignApi;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private OdsPointsController odsPointsController;
    @Resource
    private OdsTeamController odsTeamController;

    @Value("${yuke.alipay.callbackbill.url}")
    private static final String ALIPAY_NOTIFY="http://api.yuke520.com/omc/bill/billpay/AliNotify";
    private static final Logger LOG = Logger.getLogger(OdsBillPayController.class);
    private static final String UNIFIEDORDER_URL = "https://api.mch.weixin.qq.com/pay/unifiedorder";
    private static final String WX_BILL_NOTIFYURL = "http://api.yuke520.com/omc/bill/billpay/WxNotify";


    @RequestMapping(value = "/billalipay", method = RequestMethod.POST)
    public Wrapper billAliPay(@RequestBody JSONObject json) {
        System.out.println("进入支付接口");
        log.info("参数json={}",json);

        String totalpay = json.get("totalpay").toString();
        String paytype = json.get("paytype").toString();
        String billId = json.get("pay_bill_ids").toString();
        //添加支付记录
        addPayInfo(billId,paytype);

        AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
        model.setBody(paytype);
        model.setSubject("裕客网支付交易");
        model.setOutTradeNo(billId);
        model.setTimeoutExpress("30m");
        model.setTotalAmount(totalpay);
        model.setProductCode("QUICK_MSECURITY_PAY");

        AlipayTradeAppPayRequest request1 = new AlipayTradeAppPayRequest();
        request1.setBizModel(model);
        request1.setNotifyUrl(ALIPAY_NOTIFY);
        System.out.println("裕客网支付交易"+JSON.toJSONString(request1));
        try {
            //这里和普通的接口调用不同，使用的是sdkExecute
            AlipayTradeAppPayResponse response1 = Alipayutil.getAlipayClient().sdkExecute(request1);
            //就是orderString 可以直接给客户端请求，无需再做处理。
            String re = response1.getBody();
            return WrapMapper.ok(re);
        } catch (AlipayApiException e) {
            e.printStackTrace();
            return null;
        }
    }

    //微信预支付
    @PostMapping
    public Wrapper billWxPay(@RequestBody JSONObject json) throws Exception {
        String nonce_str = UUID.randomUUID().toString().replaceAll("-", "").substring(0, 32);
        // request.getRemoteAddr();
        String billrcreatip = Iputil.getLocalIpAddr();
        String payType = json.get("paytype").toString();
        //添加支付记录
        String billId = json.get("pay_bill_ids").toString();
        addPayInfo(billId,payType);

        SortedMap<Object, Object> map = new TreeMap<Object, Object>();
        map.put("appid", wxconfig.WX_APPID);
        map.put("attach", payType);
        map.put("body", "裕客网-商品交易支付");
        map.put("mch_id", wxconfig.WX_MCHID);
        map.put("notify_url", WX_BILL_NOTIFYURL);
        map.put("nonce_str", nonce_str);
        map.put("out_trade_no", billId);
        map.put("sign_type", "MD5");
        map.put("spbill_create_ip", billrcreatip);
        map.put("total_fee", Integer.valueOf(json.get("totalpay").toString()));
        map.put("trade_type", wxconfig.WX_TRADETYPE);
        String sign = payutil.createSign("UTF-8", map, wxconfig.WX_SECURITY);
        map.put("sign", sign);
        //map转xml
        Unifiedorder unifiedorder = new Unifiedorder();
        unifiedorder.setAppid(wxconfig.WX_APPID);
        //商户号
        unifiedorder.setMch_id(wxconfig.WX_MCHID);
        unifiedorder.setNonce_str(nonce_str);
        unifiedorder.setBody("裕客网-商品交易支付");
        unifiedorder.setAttach(json.get("paytype").toString());
        //订单号
        unifiedorder.setOut_trade_no(json.get("pay_bill_ids").toString());
        unifiedorder.setTotal_fee(Integer.valueOf(json.get("totalpay").toString()));
        unifiedorder.setSpbill_create_ip(billrcreatip);
        unifiedorder.setNotify_url(WX_BILL_NOTIFYURL);
        unifiedorder.setTrade_type(wxconfig.WX_TRADETYPE);
        unifiedorder.setSign(sign);
        String toXml = payutil.xmlInfo(unifiedorder);
        System.out.println(toXml);
        String back = payutil.httpsRequest(UNIFIEDORDER_URL, "POST", toXml);
        System.out.println("微信支付返回："+back);
        Map restmap = payutil.xmlToMap(back);

        SortedMap<Object, Object> payMap = new TreeMap<Object, Object>();
        if (!restmap.isEmpty() && restmap.get("return_code").equals("SUCCESS")) {
            payMap.put("appid", restmap.get("appid"));
            payMap.put("partnerid", restmap.get("mch_id"));
            payMap.put("prepayid", restmap.get("prepay_id"));
            payMap.put("package", "Sign=WXPay");
            payMap.put("noncestr", restmap.get("nonce_str"));
            payMap.put("timestamp", Long.toString(System.currentTimeMillis() / 1000));
            //二次生成签名
            payMap.put("sign", payutil.createSign("UTF-8", payMap, wxconfig.WX_SECURITY));

             return WrapMapper.ok(maptojson(payMap));
        }
        return WrapMapper.error("预支付失败");
    }


    @ResponseBody
    @RequestMapping(value = "/billpay/AliNotify", method = RequestMethod.POST)
    public String orderPayNotify(HttpServletRequest request) throws Exception {
        LOG.info("/billpay/AliNotify,收到支付宝反馈过来的信息");
        System.out.println("收到支付宝支付回调");
        //获取支付宝POST过来反馈信息
        Map<String,String> params = buildAlipayNotifyParam(request.getParameterMap());
        System.out.println(params);
        log.info("支付宝回调，{}", params);
        try {
            boolean flag = AlipaySignature.rsaCheckV1(params, Alipayutil.ALIPAY_PUBLIC_KEY, "utf-8", "RSA2");
            if (flag) {
                  // 交易是否成功
                String tradeStatus = params.get("trade_status");
                String refund = params.get("refund_fee");
                if (tradeStatus != null && (tradeStatus.equals("TRADE_SUCCESS") || tradeStatus.equals("TRADE_FINISHED"))) {

                    if (refund != null) {
                        log.info("收到支付宝的退款成功反馈");
                        Long intentId = Long.valueOf(params.get("out_trade_no"));
                        if (params.get("body").equals("Refund")) {
                            log.info("退款成功:执行相关操作：{}",intentId);
                            odsTeamIntentService.changeIntentStatus(intentId);
                        }
                        return "success";
                    }
                    log.info("支付宝的支付成功反馈");

                    if (params.get("body").equals("recharge")) {
                        Long billId = Long.valueOf(params.get("out_trade_no"));
                        String total_amount = params.get("total_amount");
                        double dTotalAmount = Double.parseDouble(total_amount);
                        double iTotalAmount = BigDecimalUtil.mul(dTotalAmount, 100).doubleValue();
                        Integer amount = (int) iTotalAmount;
                        String serial_num = params.get("trade_no");

                        //更新账单及余额,处理业务逻辑。。。

                        OdsBill odsBill = new OdsBill();
                        odsBill = (OdsBill) redisTemplate.opsForValue().get("recharge:" + billId);
                        if (odsBill == null) {
                            odsBill = odsBillService.findById(billId);
                        }
                        if (odsBill == null) {
                            return "failure";
                        }
                        odsBill.setSerialNum(serial_num);
                        //更新账单及余额
                        if (odsBill.getBalanceType().equals((byte) 0)) {
                            //更新账单表状态
                            Long userId = doBillUpdate(odsBill);

                            if (userId > 0) {
                                //发通知消息
                                messageNotify(userId, amount);

                                //充值送积分
                                addPoint(odsBill);
                                redisTemplate.delete("recharge:" + billId);
                            }
                        }
                    }else if (params.get("body").equals("teamIntent")) {
                        Long intentId = Long.valueOf(params.get("out_trade_no"));
                        String total_amount = params.get("total_amount");
                        double dTotalAmount = Double.parseDouble(total_amount);
                        double iTotalAmount = BigDecimalUtil.mul(dTotalAmount, 100).doubleValue();
                        Integer amountPaid = (int) iTotalAmount;
                        String serial_num = params.get("trade_no");

                        //更新团购支付状态和支付金额

                        OdsTeamIntent odsTeamIntent = new OdsTeamIntent();
                        odsTeamIntent = (OdsTeamIntent) redisTemplate.opsForValue().get("teamIntent:" + intentId);
                        if (odsTeamIntent == null) {
                            odsTeamIntent = odsTeamIntentService.findById(intentId);
                        }
                        if (odsTeamIntent == null) {
                            return "failure";
                        }
                        odsTeamIntent.setIntentId(intentId);
                        odsTeamIntent.setAmountPaid(amountPaid);
                        odsTeamIntent.setTradeCode(serial_num);
                        odsTeamIntent.setIntentStatus((byte)1);
                        odsTeamIntent.setPayStatus((byte)1);
                        odsTeamIntentService.update(odsTeamIntent);

                        redisTemplate.delete("teamIntent:" + intentId);
                        //更新支付表
                        updatePayInfo(intentId,amountPaid);
                        //判断是否满团，满团了关闭团
                        odsTeamController.closeTeamStatus(odsTeamIntent.getTeamId());
                    }
                    return "success";
                }else{
                    if (refund != null) {
                        log.info("支付宝的退款失败反馈");
                    }else {
                        log.info("支付宝的支付失败反馈");
                    }
                    return "success";
                }
            }

            return "failure";
        } catch (AlipayApiException e) {
            e.printStackTrace();
            return "failure";
        }

    }

    //微信返回
    @RequestMapping(value = "/billpay/WxNotify", produces = MediaType.APPLICATION_JSON_VALUE)
    @ResponseBody
    public String notifyWeiXinPay(HttpServletRequest request, HttpServletResponse response) throws Exception {
        System.out.println("微信支付回调");
        InputStream inStream = request.getInputStream();
        ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int len = 0;
        while ((len = inStream.read(buffer)) != -1) {
            outSteam.write(buffer, 0, len);
        }
        String resultxml = new String(outSteam.toByteArray(), "utf-8");
        Map<String, String> params = payutil.xmlToMap(resultxml);
        outSteam.close();
        inStream.close();
        Map<String, String> return_data = new HashMap<String, String>();
        if (!isTenpaySign(params)) {
            // 支付失败
            return_data.put("return_code", "FAIL");
            return_data.put("return_msg", "return_code不正确");
            return payutil.toXml(return_data);
        }
        else if (params.get("attach").equals("recharge")) {
            Long billId = Long.parseLong(params.get("out_trade_no").split("O")[0]);
            Integer amount = Integer.valueOf(params.get("total_fee"));
            String serial_num = params.get("transaction_id");
            //更新账单及余额
            // 处理业务逻辑。。。
            OdsBill odsBill = new OdsBill();
            odsBill = (OdsBill) redisTemplate.opsForValue().get("recharge:" + billId);
            if (odsBill == null) {
                odsBill = odsBillService.findById(billId);
            }
            if (odsBill == null) {
                return_data.put("return_code", "FAIL");
                return_data.put("return_msg", "return_code不正确");
                return payutil.toXml(return_data);
            }
            odsBill.setSerialNum(serial_num);

            if (odsBill.getBalanceType().toString().equals("0")) {
                Long userId = doBillUpdate(odsBill);

                if (userId > 0) {
                    //发通知消息
                    messageNotify(userId, amount);

                    //充值送积分
                    addPoint(odsBill);
                    redisTemplate.delete("recharge:" + billId);

                }


            }
        }else if (params.get("attach").equals("teamIntent")) {
            Long intentId = Long.parseLong(params.get("out_trade_no").split("O")[0]);
            Integer amountPaid = Integer.valueOf(params.get("total_fee"));
            String serial_num = params.get("trade_no");

            //更新团购支付状态和支付金额

            OdsTeamIntent odsTeamIntent = new OdsTeamIntent();
            odsTeamIntent = (OdsTeamIntent) redisTemplate.opsForValue().get("teamIntent:" + intentId);
            if (odsTeamIntent == null) {
                odsTeamIntent = odsTeamIntentService.findById(intentId);
            }
            if (odsTeamIntent == null) {
                return_data.put("return_code", "FAIL");
                return_data.put("return_msg", "return_code不正确");
                return payutil.toXml(return_data);
            }
            odsTeamIntent.setIntentId(intentId);
            odsTeamIntent.setAmountPaid(amountPaid);
            odsTeamIntent.setTradeCode(serial_num);
            odsTeamIntent.setIntentStatus((byte)1);
            odsTeamIntent.setPayStatus((byte)1);
            odsTeamIntentService.update(odsTeamIntent);

            redisTemplate.delete("teamIntent:" + intentId);
            //更新支付表
            updatePayInfo(intentId,amountPaid);
            //判断是否满团，满团了关闭团
            odsTeamController.closeTeamStatus(odsTeamIntent.getTeamId());
        }else if (params.get("attach").equals("Refund")) {
            Long intentId = Long.parseLong(params.get("out_trade_no").split("O")[0]);
            log.info("退款成功:执行相关操作：{}",intentId);
            odsTeamIntentService.changeIntentStatus(intentId);
        }

        //支付成功以后修改订单装填，处理逻辑等等
        return_data.put("return_code", "SUCCESS");
        return_data.put("return_msg", "OK");

        return payutil.toXml(return_data);

    }

    @Synchronized
    public Long doBillUpdate(OdsBill odsBill){
        // 处理支付成功逻辑
        try {
             //从acc_user表取amount_balance
            Wrapper wrapper = uacUserFeignApi.getUserInfoByUserId(odsBill.getUserId());
            log.info("从acc_user表取amount_balance:{}",wrapper);
            if (wrapper.getCode() == 200){
                String amountBalance = "";
                Integer amount_balance = 0;
                UserInfoDto userInfoDto = (UserInfoDto)wrapper.getResult();

                //解密
                if (userInfoDto.getAmountBalance() != null && userInfoDto.getAmountBalance() != "0"  && userInfoDto.getAmountBalance() != ""){
                    amountBalance = HttpAesUtil.decode(userInfoDto.getAmountBalance());

                    if (!amountBalance.equals("")){
                        amount_balance = Integer.valueOf(amountBalance);
                    }
                }

                //检验
                if (!amount_balance.equals(odsBill.getBalance())){
                    log.error("警告：账单表余额与用户表余额不一致，以用户表余额为准录入");
                    amount_balance = odsBill.getBalance();  //上次账单的余额
                }

                if (odsBill.getBillType().equals((byte)0)){
                    //消费
                    odsBill.setBalanceType((byte)1);
                    odsBill.setBalance(amount_balance-odsBill.getAmount());
                    odsBillService.save(odsBill);
                    //更新acc_user------账户余额----加密
                    amountBalance = HttpAesUtil.encode(String.valueOf(amount_balance - odsBill.getAmount())) ;
                }else if (odsBill.getBillType().equals((byte)4) || odsBill.getBillType().equals((byte)5) ||  odsBill.getBillType().equals((byte)6)  ){
                    //平台返现、平台佣金、取消订单返还
                    odsBill.setBalanceType((byte)1);
                    odsBill.setBalance(amount_balance+odsBill.getAmount());
                    odsBillService.save(odsBill);
                    //更新acc_user------账户余额----加密
                    amountBalance = HttpAesUtil.encode(String.valueOf(amount_balance + odsBill.getAmount())) ;
                }else if (odsBill.getBillType().equals((byte)2) || odsBill.getBillType().equals((byte)3)){
                    //充值 更新ods_bill------账户余额
                    odsBill.setBalanceType((byte)1);
                    odsBill.setBalance(amount_balance +odsBill.getAmount());
                    odsBillService.update(odsBill);
                    //更新acc_user------账户余额----加密
                     amountBalance = HttpAesUtil.encode(String.valueOf(amount_balance + odsBill.getAmount())) ;
                }

                userInfoDto.setAmountBalance(amountBalance);

                Wrapper<Integer> num = uacUserFeignApi.updateAmountBalance(userInfoDto);
                System.out.println(num);

                if (odsBill.getBillType().equals((byte)2) || odsBill.getBillType().equals((byte)3)){
                    redisTemplate.delete("recharge:" + odsBill.getBillId());
                }

                return odsBill.getUserId();

            }

            return 0L;
        } catch (Exception e) {
            LOG.error("充值回调业务处理报错,billId:" + odsBill.getBillId().toString(), e);
            return 0L;
        }

    }

    public int updateOrderStatus(OdsBill odsBill){

        List<Long> shopIds = new ArrayList<>(); // 保存店铺信息
        List<OdsOrder> odsOrders = new ArrayList<>(); // 保存订单信息

        //保存支付表
        Long getsnowid = odsOrderService.getsnowid();
        OdsPayOrder payOrder = new OdsPayOrder();
        payOrder.setPayId(getsnowid);
        payOrder.setOrderIds(odsBill.getOrderIds());
        payOrder.setAmountPaid(odsBill.getAmount());
        int num = odsPayOrderService.update(payOrder);

        String[] split = odsBill.getOrderIds().split(",");
        for (int i = 0; i < split.length; i++) {
            OdsOrder odsOrder = odsOrderService.findById(Long.valueOf(split[i]));
            if (odsOrder != null) {

                //保存到数据库，修改订单状态为已付款，未发货
                // 账户支付//订单状态已确认
                odsOrder.setPayStatus((byte) 1);
                odsOrder.setPayType((byte) 4);
                odsOrder.setPayTime(new Date());
                odsOrder.setShippingStatus((byte) 0);
                odsOrder.setOrderStatus((byte) 1);
                odsOrder.setAmountPaid(odsBill.getAmount());


                // todo 目前对于返利结算直接在订单中优惠，因此此时直接将是否返利字段置为true，20190727
                if (odsOrder != null && odsOrder.getOrderType() == 2) {
                    odsOrder.setIsCheckout(true);
                }

                odsOrderService.update(odsOrder);

                //如果此单使用了优惠券，标记使用状态
                System.out.println("如果此单使用了优惠券，标记使用状态");
                String id = "CouponReceiveIdAndOrderId:" + split[i];

                Map<String, String> map = (Map<String, String>) redisTemplate.opsForValue().get(id);
                if (null != map) {
                    cmcFeignApi.updateCouponReceive(Long.valueOf(map.get("CouponReceiveId")), Long.valueOf(split[i]));

                    redisTemplate.delete(id);
                }

                if (odsOrder.getPayType() != 0) {
                    if (odsOrder.getOrderType() == 1) {
                        redisTemplate.delete("zero:" + split[i]);
                    }
                    // 同城快送
                    if (odsOrder.getShippingType() == 2) {
                        //同时通知仓库(用rabbitmq发送)，有新订单需要打印
                        odsPayOrderService.sendMsgToWarehouse(odsOrder.getShopId().toString(), null);
                    } // shipType = 4 仓库发货
                    else if (odsOrder.getWarehouseId() != null){
                        odsPayOrderService.sendMsgToWarehouse(null, odsOrder.getWarehouseId().toString());
                    }
                }
            }//if
        }//for
        return num;
    }

    private Map<String,String> buildAlipayNotifyParam(Map requestParams) {
        Map<String, String> params = new HashMap<String, String>();

        for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext(); ) {
            String name = (String) iter.next();
            String[] values = (String[]) requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i]
                        : valueStr + values[i] + ",";
            }
            params.put(name, valueStr);
        }
        return params;
    }

    private void messageNotify(Long userId,Integer amount){
        //发通知消息
        MsgNotificationBody msg = new MsgNotificationBody();
        msg.setTitle("充值成功");
        msg.setContent("您的充值已到账，金额为"+amount/100);
        msg.setTime(new Date());
        msg.setReceiveType((byte) 3);
        msg.setOrderType((byte) 1);
        msg.setMsgType("billMsg");
        opcSendNotifyFeignApi.sendnotify(userId.toString(), "充值成功", "您的充值已到账", 0);
        opcSendNotifyFeignApi.sendnotify(userId.toString(), "充值成功", JSON.toJSONString(msg), 1);

    }

    private void addPoint(OdsBill odsBill){
        OdsPointsDto odsPointsDto = new OdsPointsDto();
        odsPointsDto.setNumber(odsBill.getAmount());
        odsPointsDto.setSerialNum(odsBill.getSerialNum());
        odsPointsDto.setUserId(odsBill.getUserId());
        odsPointsDto.setPointAspect((byte)1);
        odsPointsDto.setPointType((byte)4);
        odsPointsController.addSignIn(odsPointsDto);
    }

    private void addPayInfo(String billIds,String payType){
        Long getsnowid = null;
        OdsPayOrder payOrder = new OdsPayOrder();
        payOrder.setOrderIds(billIds);
        List<OdsPayOrder> listPayOrder = odsPayOrderService.select(payOrder);
        if (listPayOrder != null && listPayOrder.size() > 0) {
            getsnowid = listPayOrder.get(0).getPayId();
        }
        //用雪花算法生成分布式id
        if (getsnowid == null) {
            getsnowid = odsOrderService.getsnowid();
        }
        //同时生成支付表，支付表关联包含的订单ids， //out_trade_no就是payorder的id；
        OdsPayOrder odsPayOrder = new OdsPayOrder();
        odsPayOrder.setPayId(getsnowid);
        odsPayOrder.setPayTitle(payType);
        odsPayOrder.setOrderIds(billIds);

        if (listPayOrder != null && listPayOrder.size() > 0) {
            odsPayOrderService.update(odsPayOrder);
        } else {
            // 如果已经存在过订单集合，则重新支付时是每个订单单独支付，此时应删除掉原有的订单集合
            odsPayOrderService.deleteByOrderIds(billIds);

            odsPayOrderService.save(odsPayOrder);
        }
    }

    private void updatePayInfo(Long idStr,Integer totalAmount){
        OdsPayOrder payOrder = new OdsPayOrder();
        payOrder.setOrderIds(idStr.toString());
        List<OdsPayOrder> listPayOrder = odsPayOrderService.select(payOrder);

        payOrder = listPayOrder.get(0);
        payOrder.setAmountPaid(totalAmount);
        odsPayOrderService.update(payOrder);
    }
    /**
     * 支付宝退款
     *
     * @param
    */
    @PostMapping(value = "/pay/aliRefund")
    public int aliRefund(JSONObject jsonObject) {

        Object payId = jsonObject.get("out_request_no");
        Object out_trade_no = jsonObject.get("out_trade_no");
        Object refund_amount = jsonObject.get("refund_amount");

        AlipayTradeRefundRequest alipayRequest = new AlipayTradeRefundRequest(); // 统一收单交易退款接口
        // 只需要传入业务参数
        Map<String, Object> param = new HashMap<>();
        param.put("out_trade_no", out_trade_no); // 商户订单号
        param.put("refund_amount", refund_amount);// 退款金额
        param.put("refund_reason", "退款原因");// 退款原因
        param.put("out_request_no", payId); //退款单号
        param.put("body","Refund");
        alipayRequest.setBizContent(JSON.toJSONString(param)); // 不需要对json字符串转义

        try {
            AlipayTradeRefundResponse alipayResponse = Alipayutil.getAlipayClient().execute(alipayRequest);
            if (alipayResponse.isSuccess()) {
                // 调用成功，则处理业务逻辑
                if ("10000".equals(alipayResponse.getCode())) {
                    // 订单创建成功
                    LOG.info("订单退款结果：退款成功");
                    // todo 严格讲，结果只表明已经成功创建退款单，真正是否完成退款要在通知消息中才能确定，因此，后续操作应该在收到通知消息后才能处理
                    return 1;
                } else {
                    LOG.info("订单退款失败：" + alipayResponse.getMsg() + ":" + alipayResponse.getSubMsg());
                    return 0;
                }
            }
        } catch (AlipayApiException e) {
            e.printStackTrace();
            return 0;
        }

        return 0;
    }


    @PostMapping("/pay/wxRefund")
    @ApiOperation(httpMethod = "POST", value = "微信退款")
    //微信退款需要多个参数，请求参数xml格式（包括加密），请求的url，证书文件目录，证书密码
    public int wxPayBack(JSONObject jsonObject) {

        SortedMap<Object, Object> params = new TreeMap<Object, Object>();
        params.put("appid", wxconfig.WX_APPID);
        params.put("mch_id", wxconfig.WX_MCHID);
        String nonce_str = UUID.randomUUID().toString().replaceAll("-", "").substring(0, 32);
        params.put("nonce_str", nonce_str);
        params.put("out_trade_no", jsonObject.get("out_trade_no").toString());
        params.put("attach","Refund");
        //退款单号，uuid生成，保存数据库还是怎么处理
        params.put("out_refund_no", jsonObject.get("out_refund_no").toString());
        //总金额
        params.put("total_fee", jsonObject.get("total_fee").toString());
        params.put("refund_fee", jsonObject.get("refund_amount").toString());
        String sign = payutil.createSign("utf-8", params, wxconfig.WX_SECURITY);
        params.put("sign", sign);
        String requestXml = payutil.getRequestXml(params);
        //证书密码
        try {
            String s = payutil.postSSL(wxconfig.REFUND, requestXml, wxconfig.backpath, wxconfig.certpass);
            Map map = payutil.xmlToMap(s);
            String return_code = map.get("return_code").toString();
            if (return_code.equalsIgnoreCase("SUCCESS")) {
                Object result_code = map.get("result_code");
                if (result_code.equals("SUCCESS")) {
//                    return WrapMapper.ok("微信退款成功，退款金额" + map.get("refund_fee") + "(分)");
                    log.info("微信退款成功，退款金额" + map.get("refund_fee") + "(分)");
                    return 1;
                } else {
//                    return WrapMapper.error("微信退款失败");
                    log.error(map.toString());
                    log.error("微信退款失败");
                    return 0;
                }
            } else {
//                return WrapMapper.error("微信退款请求失败");
                log.error("微信退款请求失败");
                return 0;
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("微信退款异常：{}", e.getMessage());
            return -1;
        }

    }
}
